/* File Name : EventsManager.java */

package com.chenwenxuan.sync.event;

import java.util.Hashtable;

/**
 * This class encapsulates all the functional elements that internally manage the features
 * provided by this <b>Java Events Framework (JEF)</b>.
 * 
 * <p>
 * It is instantiated <i>(typically once, only)</i> by the object that will generate events
 * (which must implement the {@link IEventSource} interface).
 * <p>
 * It provides access to all the built-in management functions that keep track of <i>event listener</i>
 * objects (objects that implement the {@link IEventHandler} interface) that wish to receive event notifications.
 * <p>
 * It also provides the <i>channel</i> through which the object that is generating the events
 * (typically the object that instantiates this class) can easily notify 
 * registered listeners of the occurence of an event(s).
 * 
 * @author Jose Heitor
 * @version 1.0
 */
public class EventsManager
{
  private final IEventSource source;
  private final Hashtable<String, EventDelegate> evList;

  /**
   * Sole constructor. Creates an instance of this class and initializes it's internal sub-dependancies.
   * 
   * @param source The reference to the object that generates the events. (Typically the object
   * instantiating this class, using the <code>this</code> keyword)
   * @param evTypes The array of event names (contained in individaul Event objects) that will be generated.
   * (Each event name <b>MUST</b> be unique.)
   */
  public EventsManager(IEventSource source, Event[] evTypes)
  {
    this.source = source;
    
    // Create a separate EventDelegate instance (with its own EventDispatcher object) for each event
    // type that the source will generate. Each EventDelegate will manage any listeners that will
    // want to be notified of 'its' particular event.
    evList = new Hashtable<String, EventDelegate>();
    for (Event ev : evTypes)
    {
      registerEvent(ev);
    }
  }

public void registerEvent(Event ev) {
	if (ev.getThreadPriority() < 1)
      {
        evList.put(ev.getName(), new EventDelegate(source, ev.getName()));
      }
      else
      {
        if (ev.getQueue())
        {
          evList.put(ev.getName(), new EventDelegate(source, ev.getName(), ev.getThreadPriority(), true));
        }
        else
        {
          evList.put(ev.getName(), new EventDelegate(source, ev.getName(), ev.getThreadPriority()));
        }
      }
}
  
  /**
   * This method registers an object that whishes to be notified of a particular event.
   * 
   * @param target The reference to the <i>listener</i> object that wants to be notifiied of the event.
   * @param event The name of the event that the <i>listener</i> object wishes to be notified of.
   */
  public void addEventHandler(IEventHandler target, String event)
  {
    evList.get(event).addEventHandler(new EventObserver(target, event));
  }
  
  /**
   * This method de-registers an object that no longer whishes to be notified of a particular event.
   * 
   * @param target The reference to the registered <i>listener</i> object that no longer wants to 
   * be notifiied of the event.
   * @param event The name of the event that the registered <i>listener</i> object no longer wishes
   * to be notified of.
   */
  public void removeEventHandler(IEventHandler target, String event)
  {
    evList.get(event).removeEventHandler(target);
  }
  
  /**
   * This overloaded method dispatches an event notification to all registered <i>listeners</i>
   * of a particular event.
   * 
   * @param event The name of the event that has been fired.
   */
  public void raiseEvent(String event)
  {
    raiseEvent(event, null);
  }
  
  /**
   * This overloaded method dispatches an event notification to all registered <i>listeners</i>
   * of a particular event.
   * 
   * @param event The name of the event that has been fired.
   * @param params Reference to the <i>encapsulating</i> object through which any parameter(s)
   * associated with this event can be accessed by the notified <i>listener</i> object(s).
   */
  public void raiseEvent(String event, Object params)
  {
    evList.get(event).raiseEvent(params);
  }
}
